package org.Yiran.timetale_re.item.rune.type.functional.base;

import net.minecraft.client.Minecraft;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.PacketDistributor;
import org.Yiran.timetale_re.entity.rune.FlyingRuneEntity;
import org.Yiran.timetale_re.item.rune.base.AbstractRune;
import org.Yiran.timetale_re.item.rune.base.RuneItem;
import org.Yiran.timetale_re.network.NetworkChannel;
import org.Yiran.timetale_re.network.SCResponsePacket;

/**
 * 功能类符文基类
 * <p>
 * 该类是所有功能类符文的抽象基类，定义了功能类符文的通用行为和属性。
 * 功能类符文通常具有远程释放、飞行轨迹等特殊交互效果，通过创建飞行符文实体来实现。
 * 该类继承自AbstractRune，实现了符文的基本接口规范。
 * </p>
 */
public abstract class FunctionalRune extends AbstractRune {

    // ==============================
    // 构造方法
    // ==============================

    /**
     * 构造函数（使用默认冷却时间）
     * <p>
     * 创建一个新的功能类符文实例，使用默认的冷却时间。
     * </p>
     *
     * @param type 符文类型字符串标识，用于区分不同类型的增益符文
     */
    protected FunctionalRune(String type) {
        super(type, RuneItem.FUNCTIONAL);
    }

    /**
     * 构造函数（可自定义冷却时间）
     * <p>
     * 创建一个新的功能类符文实例，可以指定自定义的冷却时间。
     * </p>
     *
     * @param type     符文类型字符串标识，用于区分不同类型的增益符文
     * @param cooldown 符文使用后的冷却时间（单位：游戏刻，20 tick = 1秒）
     */
    protected FunctionalRune(String type, int cooldown) {
        super(type, RuneItem.FUNCTIONAL, cooldown);
    }

    // ==============================
    // 符文核心方法实现
    // ==============================

    /**
     * 使用符文时的处理逻辑
     * <p>
     * 当玩家使用功能类符文时调用此方法。该方法会播放音效，计算飞行轨迹，
     * 并在服务端创建飞行符文实体，在客户端生成视觉效果。
     * </p>
     *
     * @param stack  符文物品堆，包含具体符文信息的物品实例
     * @param level  当前世界对象，提供游戏环境上下文
     * @param player 使用符文的玩家对象
     */
    @Override
    public void onUse(ItemStack stack, Level level, Player player) {
        // 播放音效
        level.playSound(null, player.blockPosition(), SoundEvents.ENCHANTMENT_TABLE_USE,
                SoundSource.PLAYERS, 1.0F, 1.0F);

        // 获取玩家视线方向
        Vec3 lookVec = player.getLookAngle();
        Vec3 playerPos = player.position().add(0, player.getEyeHeight(), 0);

        // 计算符文飞行目标位置（在玩家前方和上方）
        Vec3 targetPos = playerPos.add(lookVec.scale(5.0)).add(0, 2.0, 0);

        if (!level.isClientSide()) {
            // 在服务端创建飞行符文实体
            FlyingRuneEntity flyingRune = new FlyingRuneEntity(level, playerPos, targetPos, stack) {
                @Override
                public void onFlightComplete() {
                    // 飞行动画结束后执行符文效果
                    executeRuneEffect(stack, level, player);
                }
            };

            // 设置所有者和符文类型信息
            flyingRune.setOwner(player);
            flyingRune.setRuneType(this.getType());

            level.addFreshEntity(flyingRune);

            // 发送数据包到客户端
            NetworkChannel.CHANNEL.send(
                    PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> flyingRune),
                    new SCResponsePacket.RunePacket(
                            flyingRune.getId(),
                            playerPos,
                            targetPos,
                            flyingRune.flightTime,
                            flyingRune.getCreationTime()
                    )
            );
        } else {
            // 在客户端生成视觉效果
            spawnFlyingRuneEntity(player, stack, playerPos, targetPos);
        }
    }

    // ==============================
    // 客户端视觉效果方法
    // ==============================

    /**
     * 在客户端生成飞行的符文实体
     * <p>
     * 在客户端环境中创建飞行符文的视觉效果，用于显示符文飞行轨迹。
     * </p>
     *
     * @param player    使用符文的玩家对象
     * @param stack     符文物品堆，包含具体符文信息的物品实例
     * @param playerPos 玩家当前位置向量
     * @param targetPos 飞行目标位置向量
     */
    @OnlyIn(Dist.CLIENT)
    private void spawnFlyingRuneEntity(Player player, ItemStack stack, Vec3 playerPos, Vec3 targetPos) {
        Minecraft mc = Minecraft.getInstance();
        if (mc.level == null) return;

        // 创建飞行符文实体
        createClientFlightEffect(playerPos, targetPos, stack);
    }

    /**
     * 创建客户端飞行效果
     * <p>
     * 在客户端环境中生成符文飞行的视觉效果，通过网络数据包与服务端同步。
     * </p>
     *
     * @param start 起始位置向量
     * @param end   目标位置向量
     * @param stack 符文物品堆，包含具体符文信息的物品实例
     */
    @OnlyIn(Dist.CLIENT)
    private void createClientFlightEffect(Vec3 start, Vec3 end, ItemStack stack) {
        Minecraft mc = Minecraft.getInstance();
        if (mc.level == null || mc.player == null) return;

        // 使用新的统一数据包
        NetworkChannel.CHANNEL.sendToServer(
                new SCResponsePacket.RunePacket(start, end, stack)
        );
    }

    // ==============================
    // 抽象方法定义
    // ==============================

    /**
     * 执行具体的符文效果（由子类实现）
     * <p>
     * 这是一个抽象方法，每个具体的功能符文子类都需要实现此方法来定义自己的功能效果。
     * 例如：生成爆炸、召唤实体、改变环境等。
     * </p>
     *
     * @param stack  符文物品堆，包含具体符文信息的物品实例
     * @param level  当前世界对象，提供游戏环境上下文
     * @param player 使用符文的玩家对象
     */
    public abstract void executeRuneEffect(ItemStack stack, Level level, Player player);

    // ==============================
    // 持续效果处理
    // ==============================

    /**
     * 功能类符文默认不处理持续效果
     * <p>
     * 重写父类方法，默认情况下功能类符文不处理持续性效果。
     * 如果具体符文需要实现持续性效果，可以重写此方法。
     * </p>
     *
     * @param stack  符文物品堆，包含具体符文信息的物品实例
     * @param level  当前世界对象，提供游戏环境上下文
     * @param player 持有符文的玩家对象
     */
    @Override
    public void onTick(ItemStack stack, Level level, Player player) {
        // 功能类符文默认不处理持续效果
        // 子类可以根据需要重写此方法
    }
}